package com.ruge.user.service.impl;

import com.ruge.core.response.Response;
import com.ruge.core.tool.AssertTool;
import com.ruge.core.tool.BaiduTool;
import com.ruge.core.tool.RedisKeyTool;
import com.ruge.tool.resource.ResourceTool;
import com.ruge.user.domain.vo.GetNearMeVo;
import com.ruge.user.error.UserError;
import com.ruge.user.service.UserLocationService;
import org.apache.commons.io.FileUtils;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ruge.wu
 * @since 2022/2/11 15:56
 */

@Service
public class UserLocationServiceImpl implements UserLocationService {

    // 展示多少用户
    private static final Integer DEFAULT_SHOW_NUM = 200;
    @Resource
    private RedisTemplate redisTemplate;
    public static List<String> strings = new ArrayList<>();

    static {
        try {
            InputStream resourceAsSteam = ResourceTool.getResourceAsSteam("school.txt");
            File file = new File("/school.txt");
            FileUtils.copyInputStreamToFile(resourceAsSteam, file);
            strings = FileUtils.readLines(file, String.valueOf(Charset.defaultCharset()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 更新用户的经纬度
     *
     * @param aid 用户aid
     * @param lon 经度
     * @param lat 纬度
     * @return {@link Response}
     */
    @Override
    public Response updateLocationByAid(Long aid, Float lon, Float lat) {
        // 构建key
        String key = RedisKeyTool.buildLocationKey();
        RedisGeoCommands.GeoLocation<Long> location = new RedisGeoCommands.GeoLocation<>(aid, new Point(lon, lat));
        redisTemplate.opsForGeo().add(key, location);
        return Response.create();
    }

    /**
     * 更新用户的经纬度
     *
     * @param aid    用户aid
     * @param radius 半径
     * @param lon    经度
     * @param lat    纬度
     * @return {@link Response}
     */
    @Override
    public Response getNearMe(Long aid, Integer radius, Double lon, Double lat) {
        String s = BaiduTool.addressByLocation(lat, lon, 100L);
        System.out.println("我的位置【" + s + "】");
        List<GetNearMeVo> list = new ArrayList<>();
        // 获取用户经纬度 没传入就到redis获取
        Point point = null;
        String key = RedisKeyTool.buildLocationKey();
        if (lon == null || lat == null) {
            List<Point> location = redisTemplate.opsForGeo().position(key, aid);
            AssertTool.mustTrue(location == null, UserError.LOCATION_NOT_ENABLED);
            point = location.get(0);
        } else {
            point = new Point(lon, lat);
        }
        // 执行redis 命令，拿到附近的人的id集合 georadius key longitude latitude radius m withdist count num
        // 距离对象，单位 m
        Distance distance = new Distance(radius, RedisGeoCommands.DistanceUnit.METERS);
        // 以用户位置为圆心，默认1000m 半径的圆
        Circle circle = new Circle(point, distance);
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        // 设置显示的条目数，包含距离，由近到远进行排序
        args.limit(DEFAULT_SHOW_NUM).includeDistance().sortAscending();
        GeoResults<RedisGeoCommands.GeoLocation<Long>> results = redisTemplate.opsForGeo().radius(key, circle, args);
        // 构建返回的结果集，把距离设置进去
        results.forEach(result -> {
            Double dis = result.getDistance().getValue();
            // 四舍五入保留一位小数；TODO 后期需要扩展处理，根据距离显示m或km
            Long targetAid = result.getContent().getName();
            // 获取当前位置中文名
            String addName;
            List<Point> location = redisTemplate.opsForGeo().position(key, targetAid);
            Point point1 = location.get(0);
            Double y = point1.getY();
            Double x = point1.getX();
            DecimalFormat df = new DecimalFormat("0.######");
//            y = Double.valueOf(df.format(y));
//            x = Double.valueOf(df.format(x));
            addName = BaiduTool.addressByLocation(y, x, 100L);
            GetNearMeVo build = GetNearMeVo.builder()
                    .aid(targetAid)
                    .distance(dis)
                    .addName(addName)
                    .lat(y)
                    .lon(x)
                    .build();
            System.out.println(build);
            list.add(build);
        });
        return Response.create(list);
    }
}
